#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <fcntl.h>

#define CMD_SIZE 100
#define UNIFIED_DIFF_CMD "diff -u "
#define APPEND ">"
#define SPACE " "
#define REPLICA_EXT ".tmp"
#define REPLICAS_FOLDER "/tmp/"
#define DIFF_FILE "mods.diff"
#define PATCH_CMD "patch"
#define DELETE_CMD "rm"

/* MINIX: PRIVATE void create_replica(const char *key){ */
void create_replica(const char *key){

	int repdes;
	char *rep_name;
	
	rep_name = malloc(100*sizeof(char ));
	strncpy(rep_name,(char*)key,sizeof(key));
	strcat((char*) rep_name,REPLICA_EXT);
	printf("Creating Replica for key: [%s]\n",key);
	
	if ((repdes = open(rep_name, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) < 0) {
		printf("Error occured while opening file\n");
		exit(-1);
	}
	memset(rep_name,0,sizeof(rep_name));
}

/* MINIX: PRIVATE void delete_replica(char *delete_cmd)*/
void delete_replica(char *delete_cmd){
	system(delete_cmd);
}

/* MINIX: PRIVATE char * construct_command(const char *key) */
char * construct_diff_cmd(const char *key){
	
	char *diff_cmd, *rep_name;
	/* FIXME: Find a way not to repeat code (see	*
	 * create_replica when creating rep_name)		*/
	rep_name = malloc(100*sizeof(char ));
	diff_cmd = malloc(CMD_SIZE*sizeof(char));
	
	strncpy(rep_name,(char*)key,sizeof(key));
	strcat((char*) rep_name,REPLICA_EXT);
	
	strncpy(diff_cmd,UNIFIED_DIFF_CMD, sizeof(UNIFIED_DIFF_CMD));
	
	/* FIXME: When integrating we have to fix an extension
	 * issue here. If DFS receives oldfile.txt we have to
	 * extract the "txt" extension from the filename and 
	 * attach "tmp". */
	strcat(diff_cmd,key);
	strcat(diff_cmd,SPACE);
	strcat(diff_cmd,rep_name);
	strcat(diff_cmd,SPACE);
	strcat(diff_cmd,APPEND);
	strcat(diff_cmd,SPACE);
	strcat(diff_cmd,DIFF_FILE);
	
	return diff_cmd;
}
/* MINIX: PRIVATE char * construct_patch_command(){ 			*/
char *construct_patch_cmd(){
	char *patch_cmd;
	patch_cmd = malloc(CMD_SIZE*sizeof(char));
	strncpy(patch_cmd,PATCH_CMD, sizeof(PATCH_CMD));
	strcat(patch_cmd,SPACE);
	strcat(patch_cmd,"<");
	strcat(patch_cmd,SPACE);
	strcat(patch_cmd,DIFF_FILE);
	return patch_cmd;
}

char *construct_delete_cmd(const char *key){
	
	char *delete_cmd, *rep_name;
	
	rep_name = malloc(NAME_MAX * sizeof(char));
	strncpy(rep_name, key,sizeof(key));
	strcat(rep_name, REPLICA_EXT);
	
	strncpy(delete_cmd,DELETE_CMD,sizeof(DELETE_CMD));
	strcat(delete_cmd,SPACE);
	strcat(delete_cmd,rep_name);
	return delete_cmd;
}

/* MINIX: PRIVATE void apply_patch(char *diff_cmd, char *patch_cmd){*/
void apply_patch(char *diff_cmd, char *patch_cmd){
	system(diff_cmd);
	system(patch_cmd);
}

int main(int argc, char **argv){
	
	int i;
	char *diff_cmd, *patch_cmd, *delete_cmd;
	for(i = 1; i< argc; i++){
		create_replica(argv[i]);
		/* IF (MODIFIED BIT IS 1) THEN */
		diff_cmd = construct_diff_cmd(argv[i]);
		patch_cmd = construct_patch_cmd();
		printf("Applying patch for key: [%s]\n", argv[i]);
		apply_patch(diff_cmd, patch_cmd);
		delete_cmd = construct_delete_cmd(argv[i]);
		printf("Deleting replica for key : [%s]\n", argv[i]);
		delete_replica(delete_cmd);
	}
	return 0;
}
